package com.jkrohn.io.countdowntimer.client;

// import java.util.Date;

import java.util.Date;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Touch;
// import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchEndHandler;
import com.google.gwt.event.dom.client.TouchMoveEvent;
import com.google.gwt.event.dom.client.TouchMoveHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Countdown_Timer implements EntryPoint {

	static Canvas canvas;
	static Canvas backBuffer;
	static long ourClock = System.currentTimeMillis();
	static long countDown;
	static Date date;

	IOBalls ioBalls;

	String[] months = { "January", "February", "March", "April", "May", "June", "July", "August",
			"September", "October", "November", "December" };
	String[] hours = { " 12 am", " 1 am", " 2 am", " 3 am", " 4 am", " 5 am", " 6 am", " 7 am",
			" 8 am", " 9 am", " 10 am", " 11 am", " 12 pm", " 1 pm", " 2 pm", " 3 pm", " 4 pm",
			" 5 pm", " 6 pm", " 7 pm", " 8 pm", " 9 pm", " 10 pm", " 11 pm" };
	// Canvas size
	static final int height = 400;
	static final int halfHeight = height / 2;
	static final int width = 760;
	static final int halfWidth = width / 2;

	// refresh rate in ms, 33 = 30fps
	static final int refreshRate = 33;

	public boolean setDate(int month, int days) {
		Date today = new Date();
		// here we're checking if the date is in next year.
		int year = 0;
		if ((today.getMonth() > month) || (today.getMonth() == month && days <= today.getDate())) {
			year++;
		}
		try {
			date = new Date(today.getYear() + year, month, days);
			return true;
		} catch (Exception e) {
			errorLabel.setText("Invalid date!!");
			return false;
		}
	}

	// putting them here so that other methods can access them
	final Button sendButton = new Button("Start Countdown");
	// final TextBox nameField = new TextBox();
	final ListBox monthsList = new ListBox();
	final TextBox dayBox = new TextBox();
	final Label errorLabel = new Label();
	static int mouseX = -200;
	static int mouseY = -200;
	static boolean mouseDown = false;

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		canvas = Canvas.createIfSupported();
		backBuffer = Canvas.createIfSupported();
		canvas.setWidth(width + "px");
		canvas.setHeight(height + "px");
		canvas.setCoordinateSpaceWidth(width);
		canvas.setCoordinateSpaceHeight(height);
		backBuffer.setCoordinateSpaceWidth(width);
		backBuffer.setCoordinateSpaceHeight(height);
		RootPanel.get("canvasContainer").add(canvas);

		// nameField.setText(Long.toString(System.currentTimeMillis()));

		dayBox.setWidth("1.5em");

		dayBox.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(com.google.gwt.event.dom.client.KeyPressEvent event) {
				// TODO Auto-generated method stub
				if (!Character.isDigit(event.getCharCode())) {
					((TextBox) event.getSource()).cancelKey();
				} else {
					boolean valid = true;
					int day = Integer.parseInt(dayBox.getText() + event.getCharCode());
					String dateStr = months[monthsList.getSelectedIndex()] + " "
							+ Integer.toString(day) + " " + (new Date().getYear() + 1900);
					try {
						Date date = new Date(dateStr);
						// System.out.println(date);
						if (date.getMonth() != monthsList.getSelectedIndex()) {
							((TextBox) event.getSource()).cancelKey();
							valid = false;
						}
					} catch (Exception e) {
						((TextBox) event.getSource()).cancelKey();
						valid = false;
					}
					if (!valid) {
						errorLabel.setText("Invalid date...");
					} else {
						errorLabel.setText("");
					}
				}
			}
		});
		final ListBox hourBox = new ListBox();
		for (String month : months) {
			monthsList.addItem(month);
		}
		monthsList.setSelectedIndex(4);
		dayBox.setValue(Integer.toString(10));
		for (String hour : hours) {
			hourBox.addItem(hour);
		}
		// nameField.setText("Google I/O 2011");

		// We can add style names to widgets
		sendButton.addStyleName("sendButton");

		// Add the nameField and sendButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		// RootPanel.get("nameFieldContainer").add(nameField);
		RootPanel.get("sendButtonContainer").add(sendButton);
		RootPanel.get("monthsListContainer").add(monthsList);
		RootPanel.get("errorLabelContainer").add(errorLabel);
		RootPanel.get("dayBoxContainer").add(dayBox);

		// Focus the cursor on the name field when the app loads
		// nameField.setFocus(true);
		// nameField.selectAll();

		// Create a handler for the sendButton and nameField
		class MyHandler implements ClickHandler, KeyUpHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				// sendNameToServer();
				System.out.println("send called...");
				if (dayBox.getText().length() == 0) {
					errorLabel.setText("Please enter a valid date.");
					return;
				}
				boolean validDate = setDate(monthsList.getSelectedIndex(),
						Integer.parseInt(dayBox.getText()));
				if (validDate) {
					errorLabel.setText("Starting countdown to " + date.toString());
				} else {
					errorLabel.setText("Invalid date!!!");
					return;
				}
				setEvent();
				startBalls();
			}

			/**
			 * Fired when the user types in the nameField.
			 */
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					// sendNameToServer();
					System.out.println("send called...");
				}
			}

			public void setEvent() {
				countDown = date.getTime();
			}

			public void startBalls() {
				if (ioBallsTimer != null) {
					ioBallsTimer.cancel();
				}
				if (ioBalls == null) {
					initHandlers();
				}
				ioBalls = new IOBalls(canvas, height, width, countDown);
				ioBalls.onDraw(canvas);
				ioBallsTimer.scheduleRepeating(refreshRate);
			}

			private void initHandlers() {

				canvas.addMouseDownHandler(new MouseDownHandler() {

					@Override
					public void onMouseDown(MouseDownEvent event) {
						// TODO Auto-generated method stub
						// System.out.println("Mouse down detected.");
						mouseDown = true;
					}
				});

				canvas.addMouseUpHandler(new MouseUpHandler() {

					@Override
					public void onMouseUp(MouseUpEvent event) {
						// TODO Auto-generated method stub
						mouseDown = false;
					}
				});

				canvas.addMouseMoveHandler(new MouseMoveHandler() {

					@Override
					public void onMouseMove(MouseMoveEvent event) {
						// TODO Auto-generated method stub
						mouseX = event.getRelativeX(canvas.getElement());
						mouseY = event.getRelativeY(canvas.getElement());
						// System.out.println(mouseX + "," + mouseY);
						IOBalls.accelGravity = true;
						IOBalls.horizontalGravityDirection = -((double) (mouseX - halfWidth) / (double) halfWidth);
						IOBalls.verticalGravityDirection = ((double) (mouseY - halfHeight) / (double) halfHeight);
						// System.out.println("Gravity: " + IOBalls.horizontalGravityDirection +
						// ", " + IOBalls.verticalGravityDirection);
					}
				});

				canvas.addMouseOutHandler(new MouseOutHandler() {
					public void onMouseOut(MouseOutEvent event) {
						mouseX = -200;
						mouseY = -200;
						IOBalls.accelGravity = false;
						IOBalls.verticalGravityDirection = 1;
						IOBalls.horizontalGravityDirection = 0;
						mouseDown = false;
						// System.out.println("Exited...");
					}
				});

				canvas.addTouchMoveHandler(new TouchMoveHandler() {

					@Override
					public void onTouchMove(TouchMoveEvent event) {
						event.preventDefault();
						if (event.getTouches().length() > 0) {
							Touch touch = event.getTouches().get(0);
							mouseX = touch.getRelativeX(canvas.getElement());
							mouseY = touch.getRelativeY(canvas.getElement());
						}
						event.preventDefault();

					}
				});

				canvas.addTouchEndHandler(new TouchEndHandler() {

					@Override
					public void onTouchEnd(TouchEndEvent event) {
						event.preventDefault();
						mouseX = -200;
						mouseY = -200;
					}
				});
			}

			final Timer ioBallsTimer = new Timer() {
				boolean running = false;

				@Override
				public void run() {
					if (!running) {
						running = true;
						ioBalls.onDraw(canvas);
						running = false;
					}
				}
			};

		}

		// Add a handler to send the name to the server
		MyHandler handler = new MyHandler();
		sendButton.addClickHandler(handler);
	}
}
